home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / imap / non-ANSI / c-client / misc.c < prev    next >
C/C++ Source or Header  |  1995-04-19  |  8KB  |  271 lines

  1. /*
  2.  * Program:    Miscellaneous utility routines
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    5 July 1988
  13.  * Last Edited:    19 April 1995
  14.  *
  15.  * Sponsorship:    The original version of this work was developed in the
  16.  *        Symbolic Systems Resources Group of the Knowledge Systems
  17.  *        Laboratory at Stanford University in 1987-88, and was funded
  18.  *        by the Biomedical Research Technology Program of the National
  19.  *        Institutes of Health under grant number RR-00785.
  20.  *
  21.  * Original version Copyright 1988 by The Leland Stanford Junior University
  22.  * Copyright 1995 by the University of Washington
  23.  *
  24.  *  Permission to use, copy, modify, and distribute this software and its
  25.  * documentation for any purpose and without fee is hereby granted, provided
  26.  * that the above copyright notices appear in all copies and that both the
  27.  * above copyright notices and this permission notice appear in supporting
  28.  * documentation, and that the name of the University of Washington or The
  29.  * Leland Stanford Junior University not be used in advertising or publicity
  30.  * pertaining to distribution of the software without specific, written prior
  31.  * permission.  This software is made available "as is", and
  32.  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  33.  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  34.  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35.  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  36.  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  37.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  38.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  39.  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  40.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41.  *
  42.  */
  43.  
  44.  
  45. #include <ctype.h>
  46. #include "mail.h"
  47. #include "osdep.h"
  48. #include "misc.h"
  49.  
  50. /* Convert string to all uppercase
  51.  * Accepts: string pointer
  52.  * Returns: string pointer
  53.  */
  54.  
  55. char *ucase (s)
  56.     char *s;
  57. {
  58.   char c;
  59.   char *ret = s;
  60.                 /* if lowercase covert to upper */
  61.   for (; c = *s; s++) if (islower (c)) *s -= 'a'-'A';
  62.   return (ret);            /* return string */
  63. }
  64.  
  65.  
  66. /* Convert string to all lowercase
  67.  * Accepts: string pointer
  68.  * Returns: string pointer
  69.  */
  70.  
  71. char *lcase (s)
  72.     char *s;
  73. {
  74.   char c;
  75.   char *ret = s;
  76.                 /* if uppercase covert to lower */
  77.   for (; c = *s; s++) if (isupper (c)) *s += 'a'-'A';
  78.   return (ret);            /* return string */
  79. }
  80.  
  81.  
  82. /* Copy string to free storage
  83.  * Accepts: source string
  84.  * Returns: free storage copy of string
  85.  */
  86.  
  87. char *cpystr (string)
  88.     char *string;
  89. {
  90.   if (string) {            /* make sure argument specified */
  91.     char *dst = (char *) fs_get (1+strlen (string));
  92.     strcpy (dst,string);
  93.     return (dst);
  94.   }
  95.   else return NIL;
  96. }
  97.  
  98. /* Returns index of rightmost bit in word
  99.  * Accepts: pointer to a 32 bit value
  100.  * Returns: -1 if word is 0, else index of rightmost bit
  101.  *
  102.  * Bit is cleared in the word
  103.  */
  104.  
  105. unsigned long find_rightmost_bit (valptr)
  106.     unsigned long *valptr;
  107. {
  108.   register long value= *valptr;
  109.   register long clearbit;    /* bit to clear */
  110.   register bitno;        /* bit number to return */
  111.   if (value == 0) return (-1);    /* no bits are set */
  112.   if (value & 0xFFFF) {        /* low order halfword has a bit? */
  113.     bitno = 0;            /* yes, start with bit 0 */
  114.     clearbit = 1;        /* which has value 1 */
  115.   } else {            /* high order halfword has the bit */
  116.     bitno = 16;            /* start with bit 16 */
  117.     clearbit = 0x10000;        /* which has value 10000h */
  118.     value >>= 16;        /* and slide the halfword down */
  119.   }
  120.   if (!(value & 0xFF)) {    /* low quarterword has a bit? */
  121.     bitno += 8;            /* no, start 8 bits higher */
  122.     clearbit <<= 8;        /* bit to clear is 2^8 higher */
  123.     value >>= 8;        /* and slide the quarterword down */
  124.   }
  125.   while (T) {            /* search for bit in quarterword */
  126.     if (value & 1) break;    /* found it? */
  127.     value >>= 1;        /* now, slide the bit down */
  128.     bitno += 1;            /* count one more bit */
  129.     clearbit <<= 1;        /* bit to clear is 1 bit higher */
  130.   }
  131.   *valptr ^= clearbit;        /* clear the bit in the argument */
  132.   return (bitno);        /* and return the bit number */
  133. }
  134.  
  135. /* Return minimum of two integers
  136.  * Accepts: integer 1
  137.  *        integer 2
  138.  * Returns: minimum
  139.  */
  140.  
  141. long min (i,j)
  142.     long i;
  143.     long j;
  144. {
  145.   return ((i < j) ? i : j);
  146. }
  147.  
  148.  
  149. /* Return maximum of two integers
  150.  * Accepts: integer 1
  151.  *        integer 2
  152.  * Returns: maximum
  153.  */
  154.  
  155. long max (i,j)
  156.     long i;
  157.     long j;
  158. {
  159.   return ((i > j) ? i : j);
  160. }
  161.  
  162. /* Case independent search (machines)
  163.     fast on 32-bit machines;
  164.  * Accepts: base string
  165.  *        length of base string
  166.  *        pattern string
  167.  *        length of pattern string
  168.  * Returns: T if pattern exists inside base, else NIL
  169.  */
  170.  
  171. #define Word unsigned long
  172.  
  173. long search (s,c,pat,patc)
  174.     char *s;
  175.     long c;
  176.     char *pat;
  177.     long patc;
  178. {
  179.   register Word m;
  180.   long cc;
  181.   union {
  182.     unsigned long wd;
  183.     char ch[9];
  184.   } wdtest;
  185.   strcpy (wdtest.ch,"AAAA1234");/* constant for word testing */
  186.                 /* validate arguments, c becomes # of tries */
  187.   if (!(s && c > 0 && pat && patc > 0 && (c -= (patc - 1)) > 0)) return NIL;
  188.                 /* do slow search if long is not 4 chars */
  189.   if (wdtest.wd != 0x41414141) return ssrc (&s,&c,pat,(long) T);
  190.   /*
  191.    * Fast search algorithm XORs the mask with each word from the base string
  192.    * and complements the result. This will give bytes of all ones where there
  193.    * are matches.  We then mask out the high order and case bits in each byte
  194.    * and add 21 (case + overflow) to all the bytes.  If we have a resulting
  195.    * carry, then we have a match.
  196.    */
  197.   if (cc = ((int) s & 3)) {    /* any chars before word boundary? */
  198.     c -= (cc = 4 - cc);        /* yes, calculate how many, account for them */
  199.                 /* search through those */
  200.     if (ssrc (&s,&cc,pat,(long) NIL)) return T;
  201.   }
  202.   m = *pat * 0x01010101;    /* search mask */
  203.   do {                /* interesting word? */
  204.     if (0x80808080&(0x21212121+(0x5F5F5F5F&~(m^*(Word *) s)))) {
  205.                 /* yes, commence a slow search through it */
  206.       if (ssrc (&s,&c,pat,(long) NIL)) return T;
  207.     }
  208.     else s += 4,c -= 4;        /* try next word */
  209.   } while (c > 0);        /* continue until end of string */
  210.   return NIL;            /* string not found */
  211. }
  212.  
  213. /* Case independent slow search within a word
  214.  * Accepts: base string
  215.  *        number of tries left
  216.  *        pattern string
  217.  *        multi-word hunt flag
  218.  * Returns: T if pattern exists inside base, else NIL
  219.  */
  220.  
  221. long ssrc (base,tries,pat,multiword)
  222.     char **base;
  223.     long *tries;
  224.     char *pat;
  225.     long multiword;
  226. {
  227.   register char *s = *base;
  228.   register long c = multiword ? *tries : min (*tries,(long) 4);
  229.   register char *p = pat;
  230.                 /* search character at a time */
  231.   if (c > 0) do if (!((*p ^ *s++) & (char) 0xDF)) {
  232.     char *ss = s;        /* remember were we began */
  233.     do if (!*++p) return T;    /* match case-independent until end */
  234.     while (!((*p ^ *s++) & (char) 0xDF));
  235.     s = ss;            /* try next character */
  236.     p = pat;            /* start at beginning of pattern */
  237.   } while (--c);        /* continue if multiword or not at boundary */
  238.   *tries -= s - *base;        /* update try count */
  239.   *base = s;            /* update base */
  240.   return NIL;            /* string not found */
  241. }
  242.  
  243. /* Wildcard pattern match
  244.  * Accepts: base string
  245.  *        pattern string
  246.  * Returns: T if pattern matches base, else NIL
  247.  */
  248.  
  249. long pmatch (s,pat)
  250.     char *s;
  251.     char *pat;
  252. {
  253.   switch (*pat) {
  254.   case '*':            /* match 0 or more characters */
  255.     if (!pat[1]) return T;    /* pattern ends with * wildcard */
  256.                 /* if still more, hunt through rest of base */
  257.     do if (pmatch (s,pat+1)) return T;
  258.     while (*s++);
  259.     break;
  260.   case '%':            /* match 1 character (RFC-1176) */
  261.   case '?':            /* match 1 character (common) */
  262.     return pmatch (s+1,pat+1);    /* continue matching remainder */
  263.   case '\0':            /* end of pattern */
  264.     return *s ? NIL : T;    /* success if also end of base */
  265.   default:            /* match this character */
  266.     return ((isupper (*pat) ? *pat + 'a'-'A' : *pat) ==
  267.         (isupper (*s) ? *s + 'a'-'A' : *s)) ? pmatch (s+1,pat+1) : NIL;
  268.   }
  269.   return NIL;
  270. }
  271.